import * as cc from 'cc';

type RState = {
    count: number;
    complete: boolean;
    cached: Promise<cc.Asset> | null;
};

export default class ResMgr {
    private states: Map<string, RState> = new Map();

    loadRes(path: string): Promise<cc.Asset> {
        if (!this.existFile(path)) {
            return Promise.reject();
        }
        let state = this.getState(path, true);
        if (!state.cached) {
            state.cached = this._loadFile(path).then((asset) => {
                state.complete = true;
                console.log('load path', path);
                return asset;
            });
        }
        state.count++;
        console.log('repeat load path', path, state.count);
        return state.cached;
    }

    _loadFile(path: string): Promise<cc.Asset> {
        return new Promise<cc.Asset>((resolve, reject) => {
            cc.resources.load(path, (error: Error, asset: cc.Asset) => {
                if (error) {
                    reject(error);
                    return;
                }
                resolve(asset);
            });
        });
    }

    // 释放文件
    public releaseFile(path: string): void {
        let state = this.getState(path);
        if (state && state.count > 0) {
            if (--state.count == 0 && state.complete) {
                this._releaseFile(path);
            }
            console.log('sub', state.count);
        }
    }

    private _releaseFile(path: string): void {
        let state = this.getState(path);
        if (state && state.complete) {
            console.log('release');
            cc.resources.release(path);
            this.states.delete(path);
        }
    }

    private getState(key: string, create?: boolean): RState {
        let state = this.states.get(key);
        if (create && !state) {
            state = { count: 0, complete: false, cached: null };
            this.states.set(key, state);
        }
        return state;
    }

    // 文件是否存在
    public existFile(path: string): boolean {
        let assetWith = null;
        let dirname = this.dirname(path) || '';
        let basename = this.basename(path) || path;
        let dirWith = cc.resources.getDirWithPath(dirname);
        for (let i = 0; i < dirWith.length; i++) {
            if (basename == this.basename(dirWith[i].path)) {
                assetWith = dirWith[i];
                break;
            }
        }
        if (!assetWith) {
            return false;
        }
        return true;
    }

    // 获取文件的基本名和目录名
    public basename(path: string, extname?: string): string {
        let index = path.indexOf('?');
        if (index > 0) path = path.substring(0, index);
        let reg = /(\/|\\)([^\/\\]+)$/g;
        let result = reg.exec(path.replace(/(\/|\\)$/, ''));
        if (!result) return path;
        let baseName = result[2];
        if (
            extname &&
            path.substring(path.length - extname.length).toLowerCase() ===
                extname.toLowerCase()
        )
            return baseName.substring(0, baseName.length - extname.length);
        return baseName;
    }

    // 获取文件的目录名
    public dirname(path: string): string {
        var temp = /((.*)(\/|\\|\\\\))?(.*?\..*$)?/.exec(path);
        return temp ? temp[2] : '';
    }
}

export const resMgr = new ResMgr();
